home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / AX25SUBR.C < prev    next >
C/C++ Source or Header  |  1989-09-02  |  14KB  |  597 lines

  1. #include "global.h"
  2. #include "mbuf.h"
  3. #include "timer.h"
  4. #include "ax25.h"
  5. #include "lapb.h"
  6. #include <ctype.h>
  7.  
  8. struct ax25_cb *ax25_cb[NHASH];
  9. struct ax25_call *ax25_digi[NHASH];
  10. struct ax25_call *ax25_call[NHASH];
  11. struct ax25_call *ax25_excl[NHASH];
  12. struct ax25_call *ax25_port;
  13.  
  14. /* Default AX.25 parameters */
  15. int16 t1init = SEC2TICK(10);    /* FRACK of 10 seconds */
  16. int16 t2init = SEC2TICK(1);    /* 1 sec acknowledgment delay */
  17. int16 t3init = 0;        /* No keep-alive polling */
  18. int16 t4init = 0;        /* No disconnection of idle links */
  19. int16 maxframe = 1;        /* Stop and wait */
  20. int16 maxsamml = 0;        /* No framesammler */
  21. int16 n2 = 10;            /* 10 retries */
  22. int16 axwindow = 2048;        /* 2K incoming text before RNR'ing */
  23. int16 paclen = 256;        /* 256-byte I fields */
  24. int16 pthresh = 128;        /* Send polls for packets larger than this */
  25.  
  26. /* Address hash function. Exclusive-ORs each byte, ignoring
  27.  * such insignificant, annoying things as E and H bits
  28.  */
  29. static
  30. int16
  31. ax25hash(s)
  32. register struct ax25_addr *s;
  33. {
  34.     register char x;
  35.  
  36.     x = s->call[0] ^ s->call[1] ^ s->call[2] ^
  37.         s->call[3] ^ s->call[4] ^ s->call[5];
  38.     x ^= s->ssid & SSID;
  39.     return (uchar(x) & 0xfe) % NHASH;
  40. }
  41. /* Look up entry in hash table */
  42. struct ax25_cb *
  43. find_ax25(dest,source)
  44. register struct ax25_addr *dest;
  45. struct ax25_addr *source;
  46. {
  47.     int16 hashval;
  48.     register struct ax25_cb *axp;
  49.     /*int i_state;*/
  50.  
  51.     /* Find appropriate hash chain */
  52.     hashval = ax25hash(dest);
  53.  
  54.     /* Search hash chain */
  55.     /*i_state = disable();*/
  56.     for(axp = ax25_cb[hashval]; axp != NULLAX25; axp = axp->next){
  57.         if(addreq(&axp->addr.dest,dest) &&
  58.            addreq(&axp->addr.source,source)){
  59.             /*restore(i_state);*/
  60.             return axp;
  61.         }
  62.     }
  63.     /*restore(i_state);*/
  64.     return NULLAX25;
  65. }
  66.  
  67. /* Remove address entry from hash table */
  68. del_ax25(axp)
  69. register struct ax25_cb *axp;
  70. {
  71.     int16 hashval;
  72.     int i;
  73.     /*int i_state;*/
  74.  
  75.     if(axp == NULLAX25)
  76.         return;
  77.     /* Remove from hash header list if first on chain */
  78.     hashval = ax25hash(&axp->addr.dest);
  79.     /*i_state = disable();*/
  80.  
  81.     /* Remove from chain list */
  82.     if(ax25_cb[hashval] == axp)
  83.         ax25_cb[hashval] = axp->next;
  84.     if(axp->prev != NULLAX25)
  85.         axp->prev->next = axp->next;
  86.     if(axp->next != NULLAX25)
  87.         axp->next->prev = axp->prev;
  88.  
  89.     /* Timers should already be stopped, but just in case... */
  90.     stop_timer(&axp->t1);
  91.     stop_timer(&axp->t2);
  92.     stop_timer(&axp->t3);
  93.     stop_timer(&axp->t4);
  94.  
  95.     /* Free allocated resources */
  96.     free_q(&axp->txq);
  97.     free_p(axp->rxasm);
  98.     free_q(&axp->rxq);
  99.     for(i = 0; i < 8; i++){
  100.         free_p(axp->sammlq[i]);
  101.         axp->sammlq[i] = NULLBUF;
  102.     }
  103.     free((char *)axp);
  104.  
  105.     /*restore(i_state);*/
  106. }
  107.  
  108. /* Create an ax25 control block. Allocate a new structure, if necessary,
  109.  * and fill it with all the defaults. The caller
  110.  * is still responsible for filling in the reply address
  111.  */
  112. struct ax25_cb *
  113. cr_ax25(dest,source)
  114. struct ax25_addr *dest,*source;
  115. {
  116.     void recover(),send_ack(),pollthem(),disc_ax25(),ax_incom();
  117.     register struct ax25_cb *axp;
  118.     int16 hashval;
  119.     /*int i_state;*/
  120.  
  121.     if(dest == NULLAXADDR || source == NULLAXADDR)
  122.         return NULLAX25;
  123.  
  124.     if((axp = find_ax25(dest,source)) == NULLAX25){
  125.         /* Not already in table; create an entry
  126.          * and insert it at the head of the chain
  127.          */
  128.         /* Find appropriate hash chain */
  129.         hashval = ax25hash(dest);
  130.         /*i_state = disable();*/
  131.         axp = (struct ax25_cb *)calloc(1,sizeof(struct ax25_cb));
  132.         if(axp == NULLAX25)
  133.             return NULLAX25;
  134.         /* Insert at beginning of chain */
  135.         axp->prev = NULLAX25;
  136.         axp->next = ax25_cb[hashval];
  137.         if(axp->next != NULLAX25)
  138.             axp->next->prev = axp;
  139.         ax25_cb[hashval] = axp;
  140.         /*restore(i_state);*/
  141.     }
  142.     axp->maxframe = maxframe;
  143.     axp->maxsamml = maxsamml;
  144.     axp->window = axwindow;
  145.     axp->paclen = paclen;
  146.     axp->proto = V2;    /* Default, can be changed by other end */
  147.     axp->pthresh = pthresh;
  148.     axp->n2 = n2;
  149.     axp->t1.start = t1init;
  150.     axp->t1.func = recover;
  151.     axp->t1.arg = (char *)axp;
  152.  
  153.     axp->t2.start = t2init;
  154.     axp->t2.func = send_ack;
  155.     axp->t2.arg = (char *)axp;
  156.  
  157.     axp->t3.start = t3init;
  158.     axp->t3.func = pollthem;
  159.     axp->t3.arg = (char *)axp;
  160.  
  161.     axp->t4.start = t4init;
  162.     axp->t4.func = disc_ax25;
  163.     axp->t4.arg = (char *)axp;
  164.  
  165.     axp->r_upcall = ax_incom;
  166.     return axp;
  167. }
  168.  
  169. /* Look up ax25 callsign entry in hash table (digi, call or excl) */
  170. struct ax25_call *
  171. find_axcall(table,addr)
  172. struct ax25_call *table[];
  173. register struct ax25_addr *addr;
  174. {
  175.     int16 hashval;
  176.     register struct ax25_call *axp;
  177.  
  178.     /* Find appropriate hash chain */
  179.     hashval = ax25hash(addr);
  180.  
  181.     /* Search hash chain */
  182.     for(axp = table[hashval]; axp != NULLAXCALL; axp = axp->next){
  183.         if(addreq(&axp->addr,addr)){
  184.             return axp;
  185.         }
  186.     }
  187.     return NULLAXCALL;
  188. }
  189.  
  190. /* Remove address entry from hash table (digi, call or excl) */
  191. del_axcall(table,axp)
  192. struct ax25_call *table[];
  193. register struct ax25_call *axp;
  194. {
  195.     int16 hashval;
  196.  
  197.     if(axp == NULLAXCALL)
  198.         return;
  199.     /* Remove from hash header list if first on chain */
  200.     hashval = ax25hash(&axp->addr);
  201.  
  202.     /* Remove from chain list */
  203.     if(table[hashval] == axp)
  204.         table[hashval] = axp->next;
  205.     if(axp->prev != NULLAXCALL)
  206.         axp->prev->next = axp->next;
  207.     if(axp->next != NULLAXCALL)
  208.         axp->next->prev = axp->prev;
  209.  
  210.     free((char *) axp);
  211. }
  212.  
  213. /* Create an ax25 call control block. Allocate a new structure, if necessary,
  214.  * and fill it with all the defaults.
  215.  */
  216. struct ax25_call *
  217. cr_axcall(table,addr)
  218. struct ax25_call *table[];
  219. struct ax25_addr *addr;
  220. {
  221.     register struct ax25_call *axp;
  222.     int16 hashval;
  223.  
  224.     if(addr == NULLAXADDR)
  225.         return NULLAXCALL;
  226.  
  227.     if((axp = find_axcall(table,addr)) == NULLAXCALL){
  228.         /* Not already in table; create an entry
  229.          * and insert it at the head of the chain
  230.          */
  231.         /* Find appropriate hash chain */
  232.         hashval = ax25hash(addr);
  233.         axp = (struct ax25_call *)calloc(1,sizeof(struct ax25_call));
  234.         if(axp == NULLAXCALL)
  235.             return NULLAXCALL;
  236.         ASSIGN(axp->addr,*addr);
  237.         /* Insert at beginning of chain */
  238.         axp->prev = NULLAXCALL;
  239.         axp->next = table[hashval];
  240.         if(axp->next != NULLAXCALL)
  241.             axp->next->prev = axp;
  242.         table[hashval] = axp;
  243.     }
  244.  
  245.     return axp;
  246. }
  247.  
  248.  
  249. /*
  250.  * setcall - convert callsign plus substation ID of the form
  251.  * "KA9Q-0" to AX.25 (shifted) address format.
  252.  * also converts the source to uppercase (uniform output)
  253.  *   Address extension bit is set (pe1chl: this seems more convenient)
  254.  *   Return -1 on error, 0 if OK
  255.  */
  256. int
  257. setcall(out,call)
  258. struct ax25_addr *out;
  259. register char *call;
  260. {
  261.     int csize;
  262.     unsigned ssid;
  263.     register int i;
  264.     register char *cp,*dp;
  265.  
  266.     if(out == (struct ax25_addr *)NULL || call == NULLCHAR || *call == '\0'){
  267.         return -1;
  268.     }
  269.     /* Find dash, if any, separating callsign from ssid
  270.      * Then compute length of callsign field and make sure
  271.      * it isn't excessive
  272.      */
  273.     dp = index(call,'-');
  274.     if(dp == NULLCHAR)
  275.         csize = strlen(call);
  276.     else
  277.         csize = (int) (dp - call);
  278.     if(csize < 3 || csize > ALEN)
  279.         return -1;
  280.     /* Now find and convert ssid, if any */
  281.     if(dp != NULLCHAR){
  282.         dp++;    /* skip dash */
  283.         ssid = atoi(dp);
  284.         if(ssid > 15)
  285.             return -1;
  286.     } else
  287.         ssid = 0;
  288.     /* Copy upper-case callsign, left shifted one bit */
  289.     cp = out->call;
  290.     for(i=0;i<csize;i++){
  291.         if(!isascii(*call) || !isalnum(*call))
  292.             return -1;
  293.         *call = toupper(*call);
  294.         *cp++ = *call++ << 1;
  295.     }
  296.     /* Pad with shifted spaces if necessary */
  297.     for(;i<ALEN;i++)
  298.         *cp++ = ' ' << 1;
  299.  
  300.     /* Insert substation ID field, set reserved bits and E(extension) */
  301.     out->ssid = 0x60 | (ssid << 1) | E;
  302.     return 0;
  303. }
  304. /*
  305.  * valid_call: validate an address according to AX.25 rules
  306.  * return 0 for valid address
  307.  */
  308. int
  309. valid_addr (addr)
  310. struct ax25_addr *addr;
  311. {
  312.     register char *cp;
  313.     register char c;
  314.     int i;
  315.  
  316.     cp = addr->call;
  317.     for(i=ALEN;i != 0;i--){
  318.         if ((c = (*cp++ >> 1) & 0x7f) == ' ' && i <= (ALEN-3))
  319.             continue;
  320.  
  321.         if (!isupper(c) && !isdigit(c))
  322.             return -1;
  323.     }
  324.     return 0;
  325. }
  326. /* Set a digipeater string in an ARP table entry */
  327. setpath(out,in,cnt)
  328. char *out;    /* Target char array containing addresses in net form */
  329. char *in[];    /* Input array of tokenized callsigns in